
package carmadness.model;

import java.util.LinkedList;
import java.util.List;

/**
 * Útelemet jelképező osztály.
 * 
 * @author Ujhelyi
 * @version 1.0
 * @created 10-Apr-2010 2:32:42 PM
 */
public class RoadSegment
{
	/**
	 * Az alapértelmezett sebességkorlátozás nagysága.
	 */
	private static float defaultSpeedLimitValue = 1.0f;
	/**
	 * Az aktuális sebességkorlátozás nagysága.
	 */
	private SpeedLimit currentSpeedLimit = new SpeedLimit();
	/**
	 * A bejövő útszakaszokat tárolja.
	 */
	private List<RoadSegmentWrapper> incomingConnections = new LinkedList<RoadSegmentWrapper>();
	/**
	 * A kimenő útszakaszokat tárolja.
	 */
	private List<RoadSegmentWrapper> outgoingConnections = new LinkedList<RoadSegmentWrapper>();
	/**
	 * Az útelemen tartózkodó jármű csomagoló osztálya.
	 */
	protected VehicleWrapper vehicle = null;

	public RoadSegment()
	{
	}

	/**
	 * Beérkező útszakasz hozzáfűzéséért felelős
	 * 
	 * @param segment
	 *            Bejövő útelem.
	 * @return Az új kapcsolatot reprezentáló RSW.
	 */
	public IncomingRoadSegmentWrapper addIncomingSegment( RoadSegment segment )
	{
		IncomingRoadSegmentWrapper wrapper = new IncomingRoadSegmentWrapper( segment, World.getInstance().getAngleByPlacement( this, segment ) );
		incomingConnections.add( wrapper );

		return wrapper;
	}

	/**
	 * Kimenő útszakasz összekötéséért felelős
	 * 
	 * @param segment
	 *            Kimenő irányú útelem.
	 * @return Az új kapcsolatot reprezentáló RSW.
	 */
	public OutgoingRoadSegmentWrapper addOutgoingSegment( RoadSegment segment )
	{
		OutgoingRoadSegmentWrapper wrapper = new OutgoingRoadSegmentWrapper( segment, World.getInstance().getAngleByPlacement( this, segment ) );
		outgoingConnections.add( wrapper );

		return wrapper;
	}

	/**
	 * Ráhelyezi az útelemre a járművet és frissti a currentSpeedLimit
	 * objektumot a rajta közlekedő jármű sebességére, ha az kisebb mint az
	 * alapértelmezett.
	 * 
	 * @param VehicleWrapper
	 *            A belépő jármű csomagolója.
	 */
	public void enter( VehicleWrapper vWrapper )
	{
		// Ha már van másik jármű az úton, legyen ütközés
		if ( vehicle != null )
		{
			vWrapper.getVehicle().accept( vehicle.getVehicle() );
		}
		// Ha még létezünk, menjünk tovább
		if ( vWrapper.getVehicle() != null )
		{
			float vehicleSpeed = vWrapper.getVehicle().getSpeed();
			currentSpeedLimit.setValue( vehicleSpeed < defaultSpeedLimitValue ? vehicleSpeed : defaultSpeedLimitValue );

			vehicle = vWrapper;
			vehicle.currentRS = this;
		}
	}

	/**
	 * Visszatér a választható irányokkal.
	 * 
	 * @return Az irányok listája.
	 */
	public List<Float> getAngles()
	{
		LinkedList<Float> list = new LinkedList<Float>();

		for ( RoadSegmentWrapper rsw : outgoingConnections )
			list.add( rsw.getAngle() );

		return list;
	}

	/**
	 * Visszatér az útelem kapcsolataival.
	 * 
	 * @return RSW lista.
	 */
	public List<RoadSegmentWrapper> getConnections()
	{
		LinkedList<RoadSegmentWrapper> connections = new LinkedList<RoadSegmentWrapper>();
		connections.addAll( incomingConnections );
		connections.addAll( outgoingConnections );

		return connections;
	}

	/**
	 * Visszatér az útelemre való belépéshez szükséges súllyal.
	 * 
	 * @return Minimális súly a belépéshez.
	 */
	public float getEntryWeight()
	{
		if ( vehicle != null ) return Float.MAX_VALUE;

		float maxTrafficWeight = 0;
		for ( RoadSegmentWrapper rsw : incomingConnections )
		{
			maxTrafficWeight = Math.max( rsw.getTrafficWeight(), maxTrafficWeight );
		}

		return maxTrafficWeight;
	}

	/**
	 * Visszaadja az adott irányban fekvő RSW-t, vagy <b>null</b>-t.
	 * 
	 * @param angle
	 *            A keresett irány.
	 * @return A keresett irányba eső RSW.
	 */
	public RoadSegmentWrapper getRSWFromAngle( float angle )
	{
		for ( RoadSegmentWrapper rsw : outgoingConnections )
			if ( Math.abs( rsw.getAngle() - angle ) < 0.01 ) return rsw;

		for ( RoadSegmentWrapper rsw : incomingConnections )
			if ( Math.abs( rsw.getAngle() - angle ) < 0.01 ) return rsw;

		return null;
	}

	/**
	 * Visszatér a currentSpeedLimit objektummal.
	 * 
	 * @return A currentSpeedLimit objektum.
	 */
	public SpeedLimit getSpeedLimit()
	{
		return currentSpeedLimit;
	}

	/**
	 * Visszatér az útelemen lévő járművel.
	 * 
	 * @return
	 */
	public VehicleWrapper getVehicle()
	{
		return vehicle;
	}

	/**
	 * <b>Null</b>-ra állítja a vehicle referenciát (vagyis elhagyja az útelemet
	 * a jármű), illetve beállítja az aktuális sebességkorlátot az
	 * alapértelmezett értékre.
	 */
	public void leave()
	{
		currentSpeedLimit.setValue( defaultSpeedLimitValue );
		vehicle = null;
	}

}
